package com.vecspace.dayu.code.pojo;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.google.common.base.CaseFormat;
import com.vecspace.data.model.IdEntity;
import com.vecspace.data.model.RowMapper;
import com.vecspace.dayu.code.consts.ColumnType;
import javax.persistence.Table;
import javax.persistence.Transient;
import com.vecspace.dicttable.DictAll;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.annotations.Polymorphism;
import org.hibernate.annotations.PolymorphismType;
import org.hibernate.annotations.Type;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

/** DAYU-表视图定义,按顺序号进行left join
 * @author wanghua
 */
@Entity
@Polymorphism(type = PolymorphismType.EXPLICIT)
@Table(name = "DAYU_CODE_DATA_TABLE")
public class DataTable implements IdEntity, java.io.Serializable {

	private static final long serialVersionUID = -2672801937276123311L;
	public DataTable(){
	}
	
	private Long id;
	/**逻辑ID*/
	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	@Column(name = "ID")
	public Long getId(){
		return id;
	}
	/**逻辑ID*/
	public void setId(Long value){
		this.id = value;
	}

	private Long funcId;
	/**数据集ID*/
	@Column(name = "FUNC_ID")
	public Long getFuncId(){
		return funcId;
	}
	/**数据集ID*/
	public void setFuncId(Long value){
		this.funcId = value;
	}

	private String tableName;
	/**功能ID*/
	@Column(name = "TABLE_NAME")
	public String getTableName(){
		return tableName;
	}
	/**功能ID*/
	public void setTableName(String value){
		this.tableName = value;
	}

	private String viewSql;
	@Column(name="VIEW_SQL")
	public String getViewSql() {
		return viewSql;
	}

	public void setViewSql(String viewSql) {
		this.viewSql = viewSql;
	}

	private String tableAliasName;
	/**表别名(统一小写)*/
	@Column(name = "TABLE_ALIAS_NAME")
	public String getTableAliasName(){
		return tableAliasName;
	}
	/**表别名(统一小写)*/
	public void setTableAliasName(String value){
		this.tableAliasName = value;
	}

	private String tableCaption;
	/**表中文名*/
	@Column(name = "TABLE_CAPTION")
	public String getTableCaption(){
		return tableCaption;
	}
	/**表中文名*/
	public void setTableCaption(String value){
		this.tableCaption = value;
	}

	private String tableRelationSubtype;
	@Column(name="TABLE_RELATION_SUBTYPE")
	public String getTableRelationSubtype() {
		return tableRelationSubtype;
	}
	public void setTableRelationSubtype(String tableRelationSubtype) {
		this.tableRelationSubtype = tableRelationSubtype;
	}
	public static String TableRelationSubtype="DAYU-CODE-004";
	@Transient
	public String getTableRelationSubtypeCaption() {
		return DictAll.getCachedItemName(TableRelationSubtype, tableRelationSubtype);
	}

	private Boolean recursion;
	@Column(name = "RECURSION_") @Type(type="org.hibernate.type.NumericBooleanType")
	public Boolean getRecursion() {
		return recursion;
	}

	public void setRecursion(Boolean recursion) {
		this.recursion = recursion;
	}
	@Transient
	public String getRecursionCaption(){
		if(recursion == null)return "否";
		return recursion?"是":"否";
	}
	private String className;
	/**类名*/
	@Column(name = "CLASS_NAME")
	public String getClassName(){
		return className;
	}
	/**类名*/
	public void setClassName(String value){
		this.className = value;
	}

	private String idColumnName;
	private String parentIdColumnName;
	private String nameColumnName;
	private String orderColumnName;
	private String filterColumnName;
	
	@Column(name = "ID_COLUMN_NAME")
	public String getIdColumnName() {
		return idColumnName;
	}

	public void setIdColumnName(String idColumnName) {
		this.idColumnName = idColumnName;
	}
	@Column(name = "PARENT_ID_COLUMN_NAME")
	public String getParentIdColumnName() {
		return parentIdColumnName;
	}
	public void setParentIdColumnName(String parentIdColumnName) {
		this.parentIdColumnName = parentIdColumnName;
	}

	@Column(name = "NAME_COLUMN_NAME")
	public String getNameColumnName() {
		return nameColumnName;
	}
	public void setNameColumnName(String nameColumnName) {
		this.nameColumnName = nameColumnName;
	}

	@Column(name = "ORDER_COLUMN_NAME")
	public String getOrderColumnName() {
		return orderColumnName;
	}
	public void setOrderColumnName(String orderColumnName) {
		this.orderColumnName = orderColumnName;
	}

	@Column(name = "FILTER_COLUMN_NAME")
	public String getFilterColumnName() {
		return filterColumnName;
	}
	public void setFilterColumnName(String filterColumnName) {
		this.filterColumnName = filterColumnName;
	}

	private String attachmentTableName;
	/**附件表表名*/
	@Column(name = "ATTACHMENT_TABLE_NAME")
	public String getAttachmentTableName(){
		return attachmentTableName;
	}
	/**附件表表名*/
	public void setAttachmentTableName(String value){
		this.attachmentTableName = value;
	}

	private String attachmentBusinessIdColumn;
	/**附件表业务ID字段*/
	@Column(name = "ATTACHMENT_BUSINESS_ID_COLUMN")
	public String getAttachmentBusinessIdColumn(){
		return attachmentBusinessIdColumn;
	}
	/**附件表业务ID字段*/
	public void setAttachmentBusinessIdColumn(String value){
		this.attachmentBusinessIdColumn = value;
	}

	private String attachmentIdColumn;
	/**附件ID字段*/
	@Column(name = "ATTACHMENT_ID_COLUMN")
	public String getAttachmentIdColumn(){
		return attachmentIdColumn;
	}
	/**附件ID字段*/
	public void setAttachmentIdColumn(String value){
		this.attachmentIdColumn = value;
	}

	private String attachmentNameColumn;
	/**附件名称字段*/
	@Column(name = "ATTACHMENT_NAME_COLUMN")
	public String getAttachmentNameColumn(){
		return attachmentNameColumn;
	}
	/**附件名称字段*/
	public void setAttachmentNameColumn(String value){
		this.attachmentNameColumn = value;
	}

	private String attachmentOrderColumn;
	/**附件排序字段*/
	@Column(name = "ATTACHMENT_ORDER_COLUMN")
	public String getAttachmentOrderColumn(){
		return attachmentOrderColumn;
	}
	/**附件排序字段*/
	public void setAttachmentOrderColumn(String value){
		this.attachmentOrderColumn = value;
	}


	private String attachmentType;
	/**附件类型 0无附件，1单个图片 2多个图片 3不限定文件类型*/
	@Column(name = "ATTACHMENT_TYPE")
	public String getAttachmentType(){
		return attachmentType;
	}
	/**附件类型 0无附件，1单个图片 2多个图片 3不限定文件类型*/
	public void setAttachmentType(String value){
		this.attachmentType = value;
	}
	public String setAttachmentTypeCaption(){
		if("1".equals(attachmentType))return "单个图片";
		if("2".equals(attachmentType))return "多个图片";
		if("3".equals(attachmentType))return "多个文件";
		return "无附件";
	}

	private String tableDesc;
	/**附件排序字段*/
	@Column(name = "TABLE_DESC")
	public String getTableDesc(){
		return tableDesc;
	}
	/**附件排序字段*/
	public void setTableDesc(String value){
		this.tableDesc = value;
	}
	
	private String foreignColumnName;
	
	private Long foreignTableId;
	
	@Column(name = "FOREIGN_COLUMN_NAME")
	public String getForeignColumnName() {
		return foreignColumnName;
	}
	public void setForeignColumnName(String foreignColumnName) {
		this.foreignColumnName = foreignColumnName;
	}
	
	@Column(name = "FOREIGN_TABLE_ID")
	public Long getForeignTableId() {
		return foreignTableId;
	}
	public void setForeignTableId(Long foreignTableId) {
		this.foreignTableId = foreignTableId;
	}
	

	private Boolean useRowLock;
	/**对本表使用记录级数据锁,0否，1是*/
	@Column(name = "USE_ROW_LOCK")@Type(type="org.hibernate.type.NumericBooleanType")
	public Boolean getUseRowLock() {
		return useRowLock;
	}
	/**对本表使用记录级数据锁,0否，1是*/
	public void setUseRowLock(Boolean useRowLock) {
		this.useRowLock = useRowLock;
	}

	private Boolean useMasterLock;
	/**由主表进行锁定,0否，1是*/
	@Column(name = "USE_MASTER_LOCK")@Type(type="org.hibernate.type.NumericBooleanType")
	public Boolean getUseMasterLock() {
		return useMasterLock;
	}
	/**由主表进行锁定,0否，1是*/
	public void setUseMasterLock(Boolean useMasterLock) {
		this.useMasterLock = useMasterLock;
	}

	private Integer ordnum;
	/**顺序号*/
	@Column(name = "ORDNUM")
	public Integer getOrdnum(){
		return ordnum;
	}
	/**顺序号*/
	public void setOrdnum(Integer value){
		this.ordnum = value;
	}

	private Date createTime;
	/**记录创建时间*/
	@JsonIgnore()
	@Column(name = "CREATE_TIME")
	public Date getCreateTime(){
		return createTime;
	}
	/**记录创建时间*/
	public void setCreateTime(Date value){
		this.createTime = value;
	}
	@Transient
	@JsonIgnore()
	public String getCreateTimeStr(){
		if(createTime == null){
			return "";
		}
		String exp = "yyyy-MM-dd";
		return new java.text.SimpleDateFormat(exp).format(createTime);
	}

	private String createUser;
	/**记录创建人ID*/
	@Column(name = "CREATE_USER")
	public String getCreateUser(){
		return createUser;
	}
	/**记录创建人ID*/
	public void setCreateUser(String value){
		this.createUser = value;
	}
	
	
	@Transient
	public String getBeanName() {
		String className = getClassName();
		if(className == null || className.length() < 1)return "";
		String beanName = className.substring(0, 1).toLowerCase() + className.substring(1);		
		return beanName;
	}

	/**将表名转为类名*/
	@Transient
	public String getTableNameAsClassName() {
		if(tableName == null || tableName.length() == 0)return "";
		String tableNameMain = tableName;
		while(tableNameMain.startsWith("_")) tableNameMain = tableNameMain.substring(1);
		while(tableNameMain.endsWith("_")) tableNameMain = tableNameMain.substring(0, tableNameMain.length()-1);
		
		int idx = tableNameMain.indexOf("_");//第一个下划线
		if(idx >0 && idx < 4) {
			tableNameMain = tableNameMain.substring(idx + 1);
			
			idx = tableNameMain.indexOf("_"); //第二个下划线
			if(idx >0 && idx < 4) {
				tableNameMain = tableNameMain.substring(idx + 1);
			}
		}
		
		String className = CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, tableNameMain);
		return className;
	}

	/**是否可以被父表锁定*/
	@Transient
	public boolean getIsLockByMaster(){
		if(useMasterLock == null)return false;
		return useMasterLock.booleanValue();
	}

	/**是否逐行锁定*/
	@Transient
	public boolean getIsLockByRow(){
		if(useRowLock == null)return false;
		return useRowLock.booleanValue();
	}


	public void parseFrom(Map<String, Object> row){
		RowMapper rowMapper = new RowMapper(row);
		this.id = rowMapper.getLong("ID");
		this.funcId = rowMapper.getLong("FUNC_ID");
		this.tableName = rowMapper.getString("TABLE_NAME");
		this.tableAliasName = rowMapper.getString("TABLE_ALIAS_NAME");
		this.tableCaption = rowMapper.getString("TABLE_CAPTION");
		this.viewSql = rowMapper.getString("VIEW_SQL");
		this.tableRelationSubtype = rowMapper.getString("TABLE_RELATION_SUBTYPE");
		this.recursion = rowMapper.getBoolean("RECURSION_");
		this.className = rowMapper.getString("CLASS_NAME");
		this.idColumnName = rowMapper.getString("ID_COLUMN_NAME");
		this.nameColumnName = rowMapper.getString("NAME_COLUMN_NAME");
		this.parentIdColumnName = rowMapper.getString("PARENT_ID_COLUMN_NAME");
		this.orderColumnName = rowMapper.getString("ORDER_COLUMN_NAME");
		this.filterColumnName = rowMapper.getString("FILTER_COLUMN_NAME");
		
		this.foreignColumnName = rowMapper.getString("FOREIGN_COLUMN_NAME");
		this.foreignTableId = rowMapper.getLong("FOREIGN_TABLE_ID");
		
		this.attachmentTableName = rowMapper.getString("ATTACHMENT_TABLE_NAME");
		this.attachmentBusinessIdColumn = rowMapper.getString("ATTACHMENT_BUSINESS_ID_COLUMN");
		this.attachmentIdColumn = rowMapper.getString("ATTACHMENT_ID_COLUMN");
		this.attachmentNameColumn = rowMapper.getString("ATTACHMENT_NAME_COLUMN");
		this.attachmentOrderColumn = rowMapper.getString("ATTACHMENT_ORDER_COLUMN");
		this.attachmentType = rowMapper.getString("ATTACHMENT_TYPE");
		this.useRowLock = rowMapper.getBoolean("USE_ROW_LOCK");
		this.useMasterLock = rowMapper.getBoolean("USE_MASTER_LOCK");
		this.tableDesc = rowMapper.getString("TABLE_DESC");
		this.ordnum = rowMapper.getInteger("ORDNUM");
		this.createTime = rowMapper.getDate("CREATE_TIME");
		this.createUser = rowMapper.getString("CREATE_USER");
	}

	@Transient
	public String getName(){
		return tableName;
	}

	@Transient
	public String getCaption(){
		return tableCaption;
	}
	
	private List<DataColumn> columns;
	
	@Transient
	public List<DataColumn> getColumns() {
		return columns;
	}
	public void setColumns(List<DataColumn> columns) {
		this.columns = columns;
	}

	@Transient
	public boolean getHasQNumberType() {
		if(columns == null || columns.size() == 0)return false;
		for(DataColumn column : columns) {
			if("QNumber".equals(column.getJavaType())) {
				return true;
			}
		}
		return false;
	}

	@Transient
	public boolean getHasQMoneyYuanType() {
		if(columns == null || columns.size() == 0)return false;
		for(DataColumn column : columns) {
			if("QMoneyYuan".equals(column.getJavaType())) {
				return true;
			}
		}
		return false;
	}
	@Transient
	public boolean getHasQMoneyWanYuanType() {
		if(columns == null || columns.size() == 0)return false;
		for(DataColumn column : columns) {
			if("QMoneyWanYuan".equals(column.getJavaType())) {
				return true;
			}
		}
		return false;
	}
	@Transient
	public boolean getHasQPercentType() {
		if(columns == null || columns.size() == 0)return false;
		for(DataColumn column : columns) {
			if("QPercent".equals(column.getJavaType())) {
				return true;
			}
		}
		return false;
	}

	@Transient
	public String getIdPropJavaType() {
		DataColumn idColumn = getIdColumn();
		if(idColumn == null)return "Long";
		return idColumn.getJavaType();
	}


	@Transient
	public String getIdPropJsType() {
		DataColumn idColumn = getIdColumn();
		if(idColumn == null)return "Long";
		return idColumn.getJsType();
	}
	
	@Transient
	public String getIdPropName() {
		DataColumn column = getIdColumn();
		if(column != null)return column.getPropName();
		return "Id";
	}

	@Transient
	public String getIdVarName() {
		DataColumn column = getIdColumn();
		if(column != null)return column.getVarName();
		return "id";
	}

	@Transient
	public DataColumn getIdColumn() {
		DataColumn column = null;
		if(columns != null) {
			column = columns.stream().filter(column2 -> StringUtils.equalsIgnoreCase(column2.getColumnName(),this.getIdColumnName())).findFirst().orElse(null);
			if(column == null) {
				column = columns.stream().filter(column2 -> ColumnType.KEY_COLUMN.equalsIgnoreCase(column2.getColumnType())).findFirst().orElse(null);
			}
		}
		return column;
	}
	
	@Transient
	public DataColumn getNameColumn() {
		DataColumn column = null;
		if(columns != null) {
			column = columns.stream().filter(column2 -> StringUtils.equalsIgnoreCase(column2.getColumnName(),this.getNameColumnName())).findFirst().orElse(null);
			if(column == null) {
				column = columns.stream().filter(column2 -> ColumnType.NAME_COLUMN.equalsIgnoreCase(column2.getColumnType())).findFirst().orElse(null);
			}
		}
		return column;
	}

	@Transient
	public String getNamePropName() {
		DataColumn column = getNameColumn();
		if(column != null)return column.getPropName();
		return "Name";
	}

	@Transient
	public String getNameVarName() {
		DataColumn column = getNameColumn();
		if(column != null)return column.getVarName();
		return "name";
	}
	
	@Transient
	public DataColumn getOrderColumn() {
		DataColumn column = null;
		if(columns != null) {

			column = columns.stream().filter(column2 -> StringUtils.equalsIgnoreCase(column2.getColumnName(),this.getOrderColumnName())).findFirst().orElse(null);

			if(column == null) {
				column = columns.stream().filter(column2 -> ColumnType.ORDER_COLUMN.equalsIgnoreCase(column2.getColumnType())).findFirst().orElse(null);
			}

			if(column == null) {
				column = columns.stream().filter(column2 -> ColumnType.NAME_COLUMN.equalsIgnoreCase(column2.getColumnType())).findFirst().orElse(null);
			}
		}
		return column;
	}

	@Transient
	public DataColumn getParentColumn() {
		DataColumn column = null;
		if(columns != null) {
			column = columns.stream().filter(column2 -> StringUtils.equalsIgnoreCase(column2.getColumnName(),this.getParentIdColumnName())).findFirst().orElse(null);
		}
		return column;
	}
	
	@Transient
	public DataColumn getForeignColumn() {
		DataColumn column = null;
		if(columns != null) {
			column = columns.stream().filter(column2 -> StringUtils.equalsIgnoreCase(column2.getColumnName(),this.getForeignColumnName())).findFirst().orElse(null);
		}
		return column;
	}

	@Transient
	public DataColumn getFilterColumn() {
		DataColumn column = null;
		if(columns != null) {
			column = columns.stream().filter(column2 -> StringUtils.equalsIgnoreCase(column2.getColumnName(),this.getFilterColumnName())).findFirst().orElse(null);
		}
		return column;
	}

	@Transient
	public DataColumn getTenantColumn() {
		DataColumn column = null;
		if(columns != null) {
			column = columns.stream().filter(column2 -> StringUtils.equalsIgnoreCase("TENANT_ID",column2.getColumnName())).findFirst().orElse(null);
		}
		return column;
	}

	/**返回所有字段的属性名（内置字段除外）
	 * 
	 * @return 
	 * @author wanghua
	 * @reviewer  
	 * @createTime 2021年10月25日 下午2:12:11
	 */
	@Transient
	public List<String> getColumnVarNames(){
		List<String> colNames = new ArrayList<>();
		if(columns != null) {
			for (DataColumn col : columns) {
				if (col.getJsonIgnore()) continue;
				colNames.add(col.getVarName());
			}
		}
		return colNames;
	}
	/**返回所有字段的属性名（内置字段除外）的字符串格式 a,b,c
	 * 
	 * @return 
	 * @author wanghua
	 * @reviewer  
	 * @createTime 2021年10月25日 下午2:12:11
	 */
	@Transient
	public String getColumnVarNamesStr(){
		return StringUtils.join(getColumnVarNames().stream().map(name->"\""+name+"\"").collect(Collectors.toList()), ',');
	}

	/**返回所有日期字段的属性名（内置字段除外）
	 * 
	 * @return 
	 * @author wanghua
	 * @reviewer  
	 * @createTime 2021年10月25日 下午2:12:11
	 */
	@Transient
	public List<String> getDateColumnVarNames(){		
		List<String> colNames = new ArrayList<>();
		if(columns == null) return colNames;
		for(DataColumn col : columns) {
			if(col.getJsonIgnore())continue;
			if(col.getIsDate() || col.getIsDateTime()) {
				colNames.add(col.getVarName());
			}
		}
		return colNames;
	}
	/**返回所有日期字段的属性名（内置字段除外）的字符串格式 a,b,c
	 * 
	 * @return 
	 * @author wanghua
	 * @reviewer  
	 * @createTime 2021年10月25日 下午2:12:11
	 */
	@Transient
	public String getDateColumnPropNamesStr(){		
		String str = StringUtils.join(getDateColumnVarNames().stream().map(name->"\""+name+"\"").collect(Collectors.toList()), ',');
		return str;
	}

	/**返回所有日期字段的属性名（内置字段除外）
	 * 
	 * @return 
	 * @author wanghua
	 * @reviewer  
	 * @createTime 2021年10月25日 下午2:12:11
	 */

	@Transient
	public List<String> getNumberColumnVarNames(){		
		List<String> colNames = new ArrayList<>();
		if(columns == null) return colNames;
		for(DataColumn col : columns) {
			if(col.getJsonIgnore())continue;
			if(col.getJavaType().equals("String"))continue;
			if(col.getJavaType().equalsIgnoreCase("LocalDate"))continue;
			if(col.getJavaType().equalsIgnoreCase("LocalDateTime"))continue;
			if(col.getJavaType().equalsIgnoreCase("Boolean"))continue;
			colNames.add(col.getVarName());
		}
		return colNames;
	}
	/**返回所有数字字段的属性名（内置字段除外）的字符串格式 a,b,c
	 * 
	 * @return 
	 * @author wanghua
	 * @reviewer  
	 * @createTime 2021年10月25日 下午2:12:11
	 */
	@Transient
	public String getNumberColumnVarNamesStr(){
		String str = StringUtils.join(getNumberColumnVarNames().stream().map(name->"\""+name+"\"").collect(Collectors.toList()), ',');
		return str;
	}
	
	public DataTable foreignTable;
	@Transient
	@JsonIgnore
	public DataTable getForeignTable() {
		return foreignTable;
	}
	public void setForeignTable(DataTable foreignTable) {
		this.foreignTable = foreignTable;
	}
//	/**根据foreignTableId查询到到表名*/
//	private String foreignTableName;
//	@Transient
//	public String getForeignTableName() {
//		return foreignTableName;
//	}
//	public void setForeignTableName(String foreignTableName) {
//		this.foreignTableName = foreignTableName;
//	}
	
	@Override
	public boolean equals(Object obj) {
		if(obj == null)return false;
		if(id == null)return false;
		DataTable other = (DataTable)obj;
		return id.equals(other.id);
	}

	@Override
	public int hashCode() {
		if(id == null)return 0;
		return id.hashCode();
	}
}
